package com.jack.payment.service.strategy;


import com.alibaba.fastjson2.JSON;
import com.jack.payment.cache.CacheRedisServiceImpl;
import com.jack.payment.constant.ResultHintConstant;
import com.jack.payment.constant.SettingRuleConstant;
import com.jack.payment.constant.enums.PaymentStatusEnum;
import com.jack.payment.dao.payment.PaymentAttachDao;
import com.jack.payment.entity.business.ApplyRefundBo;
import com.jack.payment.entity.business.PaymentInitBo;
import com.jack.payment.entity.business.RequestPayBo;
import com.jack.payment.entity.business.SupportPayChannelBo;
import com.jack.payment.entity.common.BusinessException;
import com.jack.payment.entity.generate.payment.PaymentAttachModel;
import com.jack.payment.entity.generate.user.UserApiModel;
import com.jack.payment.entity.result.ResultPayVo;
import com.jack.payment.rabbitmq.RabbitQueueSendUtil;
import com.jack.payment.util.common.TimeUtil;
import com.jack.payment.util.redis.GenerateId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

@Component
public class PaymentContext {
    private Logger log = LoggerFactory.getLogger(PaymentContext.class);

    @Autowired
    private CacheRedisServiceImpl cacheRedisService;
    @Autowired
    private Map<String, PaymentStrategy> paymentStrategyMap;
    @Autowired
    private PaymentAttachDao paymentAttachDao;
    @Autowired
    private RabbitQueueSendUtil rabbitQueueSendUtil;
    @Autowired
    private GenerateId generateId;


    /**
     * 获取不同支付方式的配置数据, 策略模式
     * @param methodBo
     * @return
     */
    public void getInitPaymentConfigData(PaymentInitBo.PaymentInitMethodBo methodBo) {
        try {
             paymentStrategyMap
                    .get(methodBo.getBeanName())
                    .updatePaymentMethodConfig(methodBo.getEnvId());
        } catch (BusinessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建不同的支付信息
     * @param requestPayBo
     * @return
     * @throws BusinessException
     */
    public ResultPayVo createPaymentInfo(RequestPayBo requestPayBo, UserApiModel userApiModel) throws BusinessException {
        List<SupportPayChannelBo> boList =
                JSON.parseArray(
                        cacheRedisService.getCacheRuleContent(SettingRuleConstant.SUPPORT_PAY_CHANNEL),
                        SupportPayChannelBo.class
                );
        ResultPayVo resultPayVo = null;
        for (SupportPayChannelBo supportPayChannel : boList) {
            if (supportPayChannel.getEnable() == 1
                    && supportPayChannel.getId().equals(requestPayBo.getChannel())) {
                try {
                    resultPayVo = paymentStrategyMap.get(supportPayChannel.getName())
                            .createPaymentInfo(requestPayBo);
                    if (resultPayVo != null) {
                        break;
                    }
                } catch (Exception e) {
                    log.error("系统不支持该{}支付方式", supportPayChannel.getName());
                    throw new BusinessException();
                }
            }
        }
        if (resultPayVo == null) {
            log.warn("生成支付信息为空, 系统设置该支付方式为关闭 或 当前支付渠道失败");
            throw new BusinessException();
        }
        paymentAttachDao.insertPayAttachContent(
                new PaymentAttachModel().builder()
                        .orderNo(requestPayBo.getOrderNo())             // 订单号
                        .channel(requestPayBo.getChannel())             // 渠道
                        .webhook(requestPayBo.getWebhook())             // 网络钩子
                        .amount(requestPayBo.getAmount())               // 支付金额
                        .attach(requestPayBo.getAttach())               // 附加数据
                        .requestTime(TimeUtil.getCurrentTime())         // 请求时间
                        .describe(requestPayBo.getDescribe())           // 支付描述
                        .payPlatform(requestPayBo.getPayPlatform())     // 支付平台
                        .status(PaymentStatusEnum.WAIT_PAY.getStat())   // 支付状态
                        .user(userApiModel.getUser())                   // 调用支付的用户
                        .apiKey(userApiModel.getApiKey())               // 此次调用的api key
                        .build());
        return  resultPayVo;
    }

    /**
     *  申请退款, 仅支持单个
     * @param requestRefundBo
     * @throws BusinessException
     */
    public void applySingleRefund(ApplyRefundBo applyRefundBo, UserApiModel userApiModel) throws BusinessException {
        PaymentAttachModel paymentAttachModel = paymentAttachDao.getAppointPayAttach(applyRefundBo.getOrderNo());
        if (paymentAttachModel == null) {
            log.warn("未找到需要退款的订单, 此订单号 或 不存在本系统");
            throw new BusinessException(ResultHintConstant.BASIC_DATA_DROP);
        }
        if (paymentAttachModel.getStatus() < 1 || paymentAttachModel.getStatus() > 3) {
            log.warn("订单状态错误, 无法进行退款操作");
            throw new BusinessException(ResultHintConstant.PAY_UPDATE);
        }
        if (!paymentAttachModel.getUser().equals(userApiModel.getId())) {
            log.warn("该api key 无权限进行调用数据");
            throw new BusinessException(ResultHintConstant.API_KEY_ERROR);
        }
        if (applyRefundBo.getAmount().compareTo(paymentAttachModel.getActualAmount()) > 0) {
            log.warn("退款金额不能大于支付金额");
            throw new BusinessException(ResultHintConstant.REFUND_AMOUNT_ERROR);
        }
        PaymentAttachModel updateRefundModel = new PaymentAttachModel().builder()
                .refundWebhook(applyRefundBo.getWebhook())
                .applyRefundAmount(applyRefundBo.getAmount())
                .orderNo(applyRefundBo.getOrderNo())
                .refundAttach(applyRefundBo.getAttach())
                .refundMqId(generateId.generateMQId())
                .build();
        paymentAttachDao.updatePayAttachContent(updateRefundModel);
    }

    /**
     * 提供订单号, 查询出当前订单所在的状态
     * @param beanName
     * @param orderNo
     */
    public void checkOrderStatus(String beanName, String orderNo) {

    }


    /**
     * 验证支付方式是否有效
     * @param beanName
     */
    public void verifyPaymentMethodValid(String beanName) {

    }


    /**
     * 检测系统全部支付系统是否有效
     */
    public void verifyAllPaymentMethodValid() {}
}
